package p.ithorns.sample.module;

import org.springframework.lang.NonNull;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import org.springframework.web.util.pattern.PathPattern;
import org.springframework.web.util.pattern.PathPatternParser;

import javax.servlet.http.HttpServletRequest;

/**
 * UrlPathCondition
 *
 * @author HtL
 * @date 2024/7/19 8:40
 * @since 1.0.0
 */
public class ModulePathCondition implements RequestCondition<ModulePathCondition> {

    private static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();

    static {
        PATH_MATCHER.setCaseSensitive(false);
        PATH_MATCHER.setPathSeparator(ModuleConst.PATH_SYMBOL);
        PATH_MATCHER.setCachePatterns(true);
        PATH_MATCHER.setTrimTokens(true);
    }

    private final String path;

    public ModulePathCondition(String path) {
        this.path = complete(path);
    }

    private String complete(final String path) {
        if (StringUtils.hasText(path) && !path.startsWith(ModuleConst.PATH_SYMBOL)) {
            return ModuleConst.PATH_SYMBOL + path;
        }

        String completion;
        if (path.equals(ModuleConst.PATH_SYMBOL)) {
            completion = ModuleConst.ROOT_PATH;
        }else if (path.equals(ModuleConst.ERROR_PATH)) {
            completion = path;
        }  else if (!path.endsWith(ModuleConst.ANY_PATH)) {
            completion = path + ModuleConst.ROOT_PATH;
        } else {
            completion = path;
        }
        return completion;
    }

    @NonNull
    @Override
    public ModulePathCondition combine(ModulePathCondition other) {
        String combine = this.path;
        if (!this.path.equals(other.path) && PATH_MATCHER.matchStart(this.path, other.path)) {
            combine = PATH_MATCHER.combine(this.path, other.path);
        }
        return new ModulePathCondition(combine);

        // 直接使用路径，不用匹配
//        if (other.path.startsWith(this.path)) {
//            return new ModulePathCondition(other.path);
//        }
//
//        return new ModulePathCondition(this.path);
    }

    @Override
    public ModulePathCondition getMatchingCondition(HttpServletRequest request) {
        String uri = request.getRequestURI();
        return PATH_MATCHER.match(this.path, uri) ? this : null;
        // return uri.startsWith(this.path) ? new ModulePathCondition(this.path) : null;
    }


    @Override
    public int compareTo(ModulePathCondition other, HttpServletRequest request) {
        if (null == this.path) {
            return -1;
        }
        if (null == other.path) {
            return 1;
        }
        return this.path.compareTo(other.path);
    }

    public static void main(String[] args) {
        String a = "/a/**";
        String b = "/A/*/B/*";
        System.out.println(PATH_MATCHER.matchStart(a, b)); // true

        System.out.println(PATH_MATCHER.combine(a, b)); // /a/*/B/*

        String uri = "/a/b/c";
        System.out.println(PATH_MATCHER.match(a, uri)); // true

        System.out.println(PATH_MATCHER.combine("/a/**", "/a/**")); // /a/**/a/**

        PathPatternParser parser = PathPatternParser.defaultInstance;
        PathPattern pa = parser.parse(a);
        PathPattern pb = parser.parse(b);
        System.out.println(pa.combine(pb));
    }
}